﻿using EBA.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;

namespace EBA.Tests.Framework
{
    [TestClass]
    public class RemotingBundleTest
    {

        [TestMethod]
        public void Test_Get_RemotingProcessBundle()
        {
            using (var bundleContext = new RemotingProcessBundleContext())
            {
                bundleContext.Initialize<IBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "EBA.Tests.Framework.MyBundle");
                Assert.AreEqual("EBA.Tests.Framework.MyBundle", bundleContext.Bundle.Id);
            }
        }

        [TestMethod]
        public void Test_Get_RemotingThreadBundle()
        {
            using (var bundleContext = new RemotingThreadBundleContext())
            {
                bundleContext.Initialize<IBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "EBA.Tests.Framework.MyBundle");
                Assert.AreEqual("EBA.Tests.Framework.MyBundle", bundleContext.Bundle.Id);
            }
        }

        [TestMethod]
        public void Test_Get_RemotingProcessBundleService()
        {
            using (var bundleContext = new RemotingProcessBundleContext())
            {
                bundleContext.Initialize<IBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "EBA.Tests.Framework.MyBundle2");

                bundleContext.Bundle.Start();

                var service = bundleContext.GetService<IBundleService>();

                Assert.AreEqual("MyBundleService", service.GetServiceName());
            }
        }

        [TestMethod]
        public void Test_Get_RemotingThreadBundleService()
        {
            using (var bundleContext = new RemotingThreadBundleContext())
            {
                bundleContext.Initialize<IBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "EBA.Tests.Framework.MyBundle2");

                bundleContext.Bundle.Start();

                var service = bundleContext.GetService<IBundleService>();

                Assert.AreEqual("MyBundleService", service.GetServiceName());
            }
        }

        [TestMethod]
        public void Test_Get_RemotingProcessRuntimeService()
        {
            using (var bundleContext = new RemotingProcessBundleContext())
            {

                bundleContext.Initialize<IBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "EBA.Tests.Framework.DuplexBundle");

                var service = new BundleService("RemotingRuntimeService");
                bundleContext.RegisterService<IBundleService>(service);

                //change service name into "DuplexBundle"
                bundleContext.Bundle.Start();

                Assert.AreEqual("DuplexBundle", service.GetServiceName());
            }
        }

        [TestMethod]
        public void Test_Get_RemotingThreadRuntimeService()
        {
            using (var bundleContext = new RemotingThreadBundleContext())
            {

                bundleContext.Initialize<IBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "EBA.Tests.Framework.DuplexBundle");

                var service = new BundleService("RemotingRuntimeService");
                bundleContext.RegisterService<IBundleService>(service);

                //change service name into "DuplexBundle"
                bundleContext.Bundle.Start();

                Assert.AreEqual("DuplexBundle", service.GetServiceName());
            }
        }

        [TestMethod]
        public void get_remoting_process_custome_bundle()
        {
            using (var bundleContext = new RemotingProcessBundleContext())
            {

                bundleContext.Initialize<ICustomBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "CustomBundle");

                var customBundle = bundleContext.Bundle as ICustomBundle;

         
                Assert.IsNotNull(customBundle);
                Assert.AreEqual("CustomBundle",customBundle.InvokeCustomMethod());
            }
        }

        [TestMethod]
        public void get_remoting_thread_custome_bundle()
        {
            using (var bundleContext = new RemotingThreadBundleContext())
            {

                bundleContext.Initialize<ICustomBundle>(Guid.NewGuid().ToString("N"), AppRuntime.AssemblyPath, "CustomBundle");

                var customBundle = bundleContext.Bundle as ICustomBundle;


                Assert.IsNotNull(customBundle);
                Assert.AreEqual("CustomBundle", customBundle.InvokeCustomMethod());
            }
        }

        #region CustomBundle
        public interface ICustomBundle : IBundle
        {
            string InvokeCustomMethod();
        }

        [Export("CustomBundle", typeof(ICustomBundle))]
        [Serializable]
        public class CustomBundle : MarshalByRefObject, ICustomBundle
        {
    
            public string InvokeCustomMethod()
            {
                return "CustomBundle";
            }

            public IBundleContext BundleContext
            {
                get;
                set;
            }

            public void Start()
            {

            }

            public void Stop()
            {

            }

            public string Id
            {
                get { return "CustomBundle"; }
            }

            public string Name
            {
                get { return "CustomBundle"; }
            }

            public string Description
            {
                get { return "CustomBundle"; }
            }

            public Version Version
            {
                get { return new Version(0, 0, 0); }
            }


            public BundleState State
            {
                get { throw new NotImplementedException(); }
            }


            public string StartupPath
            {
                set { throw new NotImplementedException(); }
            }
        } 
        #endregion

        #region Helpers
        [Export("EBA.Tests.Framework.MyBundle", typeof(IBundle))]
        [Export("EBA.Tests.Framework.MyBundle2", typeof(IBundle))]
        public class MyBundle : IBundle
        {
            public IBundleContext BundleContext
            {
                get;
                set;
            }

            public void Start()
            {
                this.BundleContext.RegisterService<IBundleService>(new BundleService("MyBundleService"));
            }

            public void Stop()
            {

            }

            public string Id
            {
                get
                {
                    return "EBA.Tests.Framework.MyBundle";
                }
            }

            public string Name
            {
                get
                {
                    return "MyBundle";
                }
            }

            public string Description
            {
                get { return "MyBundle"; }
            }

            public Version Version
            {
                get { return this.GetType().Assembly.GetName().Version; }
            }


            public BundleState State
            {
                get { throw new NotImplementedException(); }
            }


            public string StartupPath
            {
                set { throw new NotImplementedException(); }
            }
        }

        [Export("EBA.Tests.Framework.DuplexBundle", typeof(IBundle))]
        public class DuplexBundle : IBundle
        {
            public IBundleContext BundleContext
            {
                get;
                set;
            }

            public void Start()
            {
                var service = this.BundleContext.GetService<IBundleService>();
                service.SetServiceName("DuplexBundle");
            }

            public void Stop()
            {
                //throw new NotImplementedException();
            }

            public string Id
            {
                get
                {
                    return "EBA.Tests.Framework.DuplexBundle";
                }
            }

            public string Name
            {
                get
                {
                    return "DuplexBundle";
                }
            }

            public string Description
            {
                get { return "DuplexBundle"; }
            }

            public Version Version
            {
                get { return this.GetType().Assembly.GetName().Version; }
            }


            public BundleState State
            {
                get { throw new NotImplementedException(); }
            }


            public string StartupPath
            {
                set { throw new NotImplementedException(); }
            }
        }

        public interface IBundleService
        {
            string GetServiceName();
            void SetServiceName(string newName);
        }

        public class BundleService : IBundleService
        {
            public BundleService(string name)
            {
                this._Name = name;
            }


            string _Name;
            public string GetServiceName()
            {
                return this._Name;
            }

            public void SetServiceName(string newName)
            {
                this._Name = newName;
            }


        }
        #endregion
    }

    
}
